# -*- coding:utf-8 -*-

#该模块用于查找文件目录和文件
import glob
import os.path
import numpy as np
import tensorflow as tf
from tensorflow.python.platform import gfile

#原始输入数据的目录，这个目录下有五个子目录，每个子目录下保存属于该类别的所有图片
input_data='/path/flower_photos'
#输出文件地址，将整理后的图片数据通过numpy的格式保存，在第七章中将更加详细的介绍数据预处理，这里暂时用numpy
output_file='path/flower_processed_data.npy'

#测试数据和验证数据比例
validation_percentage=10
test_percentage=10

#读取数据并将数据分割成训练数据，验证数据和测试数据
def create_image_lists(sess,testing_percentage,validation_percentage):
    sub_dirs=[x[0] for x in os.walk(input_data)]
    is_root_dir=True

    #初始化各个数据集
    training_images=[]
    training_labels=[]
    testing_images=[]
    testing_labels=[]
    validation_images=[]
    validation_labels=[]
    current_label=0

    #读取所有的子目录
    for sub_dir in sub_dirs:
        if is_root_dir:
            #一开始会跳过一个，因为第一个为根目录的三元组，后面五个才为子目录
            is_root_dir=False
            continue

        #获取一个子目录中的所有图片文件
        extensions=['jpg','jpeg','JPG','JPEG']
        file_list=[]    #图片文件名列表
        dir_name=os.path.basename(sub_dir)    #返回当前路径的最后一部分，相当于sub_dir的文件名
        for extension in extensions:
            file_glob=os.path.join(input_data,dir_name,'*,'+extension)
            #extend()用于在列表末尾一次性追加另一个序列中的多个值
            #glob.glob()用于匹配路径中符合条件的字符串列表，这里得到的是某文件下的所有图片名
            file_list.extend(glob.glob(file_glob))

        if not file_list:continue

        #处理图片数据
        for file_name in file_list:
            #读取并解析图片，将图片转化为299*299以便Inception-v3模型来处理
            #更多关于图像预处理的内容将在第七章中介绍

            #读取图片
            image_raw_data=gfile.FastGFile(file_name,'rb').read()
            #图像解码
            image=tf.image.decode_jpeg(image_raw_data)
            if image.dtype!=tf.float32:
                image=tf.image.convert_image_dtype(image,dtype=tf.float32)
            image=tf.image.resize_images(image,[299,299])
            image_value=sess.run(image)

            #随机划分数据集
            chance=np.random.randint(100)   #产生一个离散均匀分布的整数<100
            if chance<validation_percentage:
                validation_images.append(image_value)
                validation_labels.append(current_label)
            elif chance<(testing_percentage+validation_percentage):
                testing_images.append(image_value)
                testing_labels.append(current_label)
            else:
                training_images.append(image_value)
                training_labels.append(current_label)
        current_label += 1

    #将训练数据随机打乱以获得更好的训练效果
    #这里很重要，看下面的组合操作s
    state=np.random.get_state()    #记录数组被打乱的操作，可理解为设定状态
    np.random.shuffle(training_images)      #开始打乱
    np.random.set_state(state)             #接收前面的状态，可以利用状态进行相同的操作
    np.random.shuffle(training_labels)     #按相同方式打乱标记

    #上面组合操作，将实例和实例的标签同时打乱，并可以保证打乱后两个数组仍是一一对应关系
    return np.asarray([training_images,training_labels,validation_images,validation_labels,testing_images,testing_labels])

#数据整理主函数
def main():
    with tf.Session() as sess:
        processed_data=create_image_lists(
            sess,test_percentage,validation_percentage
        )
        #通过numpy格式保存处理后的数据,后缀为npy
        np.save(output_file,processed_data)

if __name__=='__main__':
    main()